package com.cskaoyan.mall.payment.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cskaoyan.mall.common.constant.RedisConst;
import com.cskaoyan.mall.common.constant.ResultCodeEnum;
import com.cskaoyan.mall.common.execption.BusinessException;
import com.cskaoyan.mall.order.constant.OrderStatus;
import com.cskaoyan.mall.order.dto.OrderInfoDTO;
import com.cskaoyan.mall.payment.alipay.AlipayHelper;
import com.cskaoyan.mall.payment.alipay.PayHelper;
import com.cskaoyan.mall.payment.alipay.factory.PayHelperFactory;
import com.cskaoyan.mall.payment.client.OrderApiClient;
import com.cskaoyan.mall.payment.constant.PaymentStatus;
import com.cskaoyan.mall.payment.constant.PaymentType;
import com.cskaoyan.mall.payment.converter.PaymentInfoConverter;
import com.cskaoyan.mall.pay.api.dto.PaymentInfoDTO;
import com.cskaoyan.mall.payment.mapper.PaymentInfoMapper;
import com.cskaoyan.mall.payment.model.PaymentInfo;
import com.cskaoyan.mall.payment.service.PayService;
import kotlin.jvm.internal.Lambda;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;

/**
 * @author Macro_Ray
 * @since 2024/6/25 下午2:33
 */
@Service
@SuppressWarnings("all")
@Slf4j
public class PayServiceImpl implements PayService {

    @Autowired
    OrderApiClient orderApiClient;
    @Autowired
    RedissonClient redissonClient;
    @Autowired
    PaymentInfoConverter paymentInfoConverter;
    @Autowired
    PaymentInfoMapper paymentInfoMapper;
    @Autowired
    PayHelperFactory payHelperFactory;

    /**
     * 支付宝支付，获取支付表单
     */
    @Override
    public String createAliPay(Long orderId) {
        // 1 判断订单状态，如果订单状态为 close或paid 状态
        OrderInfoDTO orderInfoDTO = orderApiClient.getOrderInfoDTO(orderId);
        if (OrderStatus.CLOSED.name().equals(orderInfoDTO.getOrderStatus())||OrderStatus.PAID.name().equals(orderInfoDTO.getOrderStatus())){
            return "订单已支付或者已取消";
        }

        // 2 在 payment_info 中保存订单相关的一条支付记录
        savePaymentInfo(orderInfoDTO,PaymentType.ALIPAY.name());   // 现在我们只有一个支付宝支付所以只有一个支付方式，可以有多个支付方式

        // 3 获取支付二维码页面对应的表单字符串
        PayHelper aliPayHelper = payHelperFactory.getPayHelper(PaymentType.ALIPAY);
        String form = aliPayHelper.prePay(orderInfoDTO);

        return form;
    }

    /**保存订单相关的一条支付记录*/
    @Override
    public void savePaymentInfo(OrderInfoDTO orderInfo, String paymentTypeName) {
        // 根据 orderId 、支付方式去 查询订单
        LambdaQueryWrapper<PaymentInfo> paymentInfoQueryWrapper = new LambdaQueryWrapper<>();
        // orderId
        paymentInfoQueryWrapper.eq(PaymentInfo::getOrderId,orderInfo.getId());
        // 支付方式
        paymentInfoQueryWrapper.eq(PaymentInfo::getPaymentType,paymentTypeName);

        PaymentInfo paymentInfo = paymentInfoMapper.selectOne(paymentInfoQueryWrapper);
        if (paymentInfo != null){
            // 如果存在，什么都不返回
            return;
        }
        // 否则，新增一条支付记录
        PaymentInfo payment = paymentInfoConverter.contvertOrderInfoDTO2PaymentInfo(orderInfo);

        // 指定支付方式
        payment.setPaymentStatus(PaymentStatus.UNPAID.name());         // 支付中
    }


    /**
     * 通过外部交易号和交易渠道 查询支付记录
     */
    @Override
    public PaymentInfoDTO queryPaymentInfoByOutTradeNoAndPaymentType(String outTradeNo, String payTypeName) {

        return null;
    }

    /**
     * 修改支付记录表
     * 1. 更改状态
     * 2. 设置回调信息
     * 3. 假如出现异常，删除回调幂等标记
     */
    @Override
    @Transactional
    public Boolean successPay(String outTradeNo, String payTypeName, Map<String, String> paramsMap) {

        try {
            // 1 修改支付记录的状态为 已支付
            LambdaQueryWrapper<PaymentInfo> paymentInfoQueryWrapper = new LambdaQueryWrapper<>();
            paymentInfoQueryWrapper.eq(PaymentInfo::getOutTradeNo, outTradeNo)
                    .eq(PaymentInfo::getPaymentType,payTypeName);
            PaymentInfo paymentInfo = paymentInfoMapper.selectOne(paymentInfoQueryWrapper);

            // 修改支付成功后 支付记录表 的属性
            paymentInfo.setUpdateTime(new Date());   // 更新时间
            paymentInfo.setPaymentStatus(PaymentStatus.PAID.name());  // 更新支付状态
            paymentInfo.setCallbackTime(new Date());  // 设置异步回调时间
            paymentInfo.setCallbackContent(JSON.toJSONString(paramsMap));  // 设置异步回调信息
            paymentInfo.setTradeNo(paramsMap.get("trade_no"));          // 设置支付宝交易号
            // 更新
            paymentInfoMapper.updateById(paymentInfo);

            // 2 修改订单的状态为 已支付
            orderApiClient.successPay(paymentInfo.getOrderId());

        } catch (Exception e) {
            // 出现异常，删除重复的标记才能再次发送通知
            String notifyId = paramsMap.get("notify_id");
            boolean delete = redissonClient.getBucket(RedisConst.PAY_CALL_BACK_VERFY_PREFIX + notifyId).delete();
        }


        // 设置回调信息

        return true;
    }

    @Override
    public void updatePaymentStatus(String outTradeNo, String payTypeName, PaymentStatus paymentStatus) {

    }
}
